<template>
  <div class="wapper" v-show="!isadd">
    <div class="left">
      <!-- //##树型控件 -->
      <el-input placeholder="输入姓名进行搜索" v-model="keyword"></el-input>

      <el-tree
        v-loading="loadingTree"
        style="max-width: 600px"
        :data="treeArr"
        :props="defaultProps"
        @node-click="nodeClick"
        :default-expand-all="true"
        :highlight-current="true"
        :expand-on-click-node="false"
        :check-on-click-node="true"
      />
      <!-- show-checkbox  
        @check="handleCheckChange" -->
    </div>
    <div class="right">
      <div class="title" style="padding-right: 30px; margin: 20px 0">
        <el-button @click="sendMessage">群发通知</el-button>
        <div>
          <el-button type="primary" @click="router.push('/addStaff')">添加员工</el-button>
          <el-button type="primary" plain @click="visbleExcel = true"
            >excel导入</el-button
          >
          <el-popconfirm title="是否导出选中的列表项" @confirm="excelExport">
            <template #reference>
              <el-button type="primary" plain>excel导出</el-button>
            </template>
          </el-popconfirm>
        </div>
      </div>
      <!-- //##列表 -->
      <el-table
        v-loading="loadingTable"
        @selection-change="handleSelectionChange"
        :data="list"
        style="width: 100%"
      >
        <el-table-column type="selection" width="55" />
        <el-table-column prop="staffPhoto" label="头像">
          <template #default="scope">
            <img
              style=""
              v-show="scope.row.staffPhoto"
              :src="scope.row.staffPhoto"
              alt=""
            />
            <div class="tou" v-show="!scope.row.staffPhoto">
              {{ scope.row.staffPhoto || scope.row.username.substring(0, 1) }}
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="username" label="姓名" />
        <el-table-column prop="mobile" label="手机号" />
        <el-table-column prop="workNumber" label="工号" />
        <el-table-column prop="formOfEmployment" label="聘用形式">
          <template #default="scope">
            <span>{{ scope.row.formOfEmployment == 1 ? "正式" : "非正式" }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="departmentName" label="部门" />
        <el-table-column prop="timeOfEntry" label="入职时间" />
        <el-table-column prop="" label="操作" width="150">
          <template #default="scope">
            <el-button size="small" @click="look(scope.row.id)" type="primary" text
              >查看</el-button
            >
            <el-button size="small" @click="role(scope.row.id)" type="primary" text
              >角色</el-button
            >

            <el-popconfirm title="确定删除？" @confirm="del(scope.row.id)">
              <template #reference>
                <el-button size="small" text type="primary"> 删除 </el-button>
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>
      <div class="pagination">
        <!--//## 分页 -->
        <el-pagination
          v-model:current-page="page"
          v-model:page-size="pagesize"
          :page-sizes="[5, 8, 12]"
          layout="total,prev, pager, next "
          :total="total"
          @change="changePage"
        />
      </div>
    </div>

    <!-- //##角色列表的弹框 -->
    <el-dialog v-model="dialogVisible" title="分配角色" width="500">
      <el-checkbox-group v-model="roleIds">
        <el-checkbox v-for="k in roleList" :key="k.id" :label="k.name" :value="k.id" />
      </el-checkbox-group>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="confirm()"> 确认修改 </el-button>
        </div>
      </template>
    </el-dialog>

    <!-- //##导入用的弹框 -->
    <el-dialog v-model="visbleExcel" title="导入excel" width="500">
      <!-- 文件上传 -->
      <el-upload
        :show-file-list="false"
        :drag="true"
        :on-change="fileChange"
        :auto-upload="false"
      >
        <!-- <el-button type="primary">支持拖拽上传</el-button> -->
        <div class="file">
          <img v-if="!file" src="@/assets/icon/上传.png" alt="" />
          <span v-if="file">{{ file.name }}</span>
        </div>
        <template #tip>
          <div class="el-upload__tip"></div>
        </template>
      </el-upload>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="visbleExcel = false">取消</el-button>
          <el-button type="primary" @click="xiazai"> 点击下载模板 </el-button>
          <el-button type="primary" @click="importExcel"> 确认导入 </el-button>
        </div>
      </template>
    </el-dialog>

    <!-- //##发送消息的弹框 -->
    <popUp
      title="群发消息"
      width="700"
      ref="xiaoxiRef"
      :confirm="sureSendMsg"
      :xiao="cancel"
    >
      <template #cont>
        <div class="staffs tem">
          <el-tag v-for="k in staffs" :key="k.id" closable @close="closeStaff(k.id)">
            {{ k.username }}
          </el-tag>
        </div>
        <div class="tem">
          <span class="title">消息类型： </span>
          <el-select v-model="msgType" placeholder="选择消息类型" style="width: 240px">
            <el-option
              v-for="item in msgGrade"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </div>
        <div class="tem">
          <span class="title">消息内容：</span><br />
          <el-input
            v-model="msgContent"
            style="width: 400px"
            :rows="3"
            type="textarea"
            placeholder="输入信息内容"
          />
        </div>
      </template>
    </popUp>
  </div>

  <RouterView v-show="isadd"></RouterView>
</template>

<script setup>
import { ref, onMounted, watch, watchEffect } from "vue";
import { useRouter, useRoute } from "vue-router";
let router = useRouter();

let route = useRoute();
import { ElMessage } from "element-plus";
import axios from "@/utils/request";
import popUp from "@/components/popUp.vue";
// excel的导入和导出
import ExcelJS from "exceljs";
import FileSaver from "file-saver";
// import XLSX from 'xlsx';
import * as XLSX from "xlsx";

let list = ref([]);
let multipleSelection = ref([]); //选中列表
let page = ref(1);
let pagesize = ref(5);
let total = ref();
let keyword = ref("");
let departmentId = ref(1);
let treeArr = ref([]); //树型控件的数据
let isadd = ref(false); //判断是不是再添加或者修改员工信息进行切换显示路由
const defaultProps = {
  children: "children",
  label: "name",
}; //要渲染数据的哪一个字段
let dialogVisible = ref(false);
let roleList = ref([]); //所有的角色列表
let roleIds = ref([]); //当前选中的角色id
let roleId = ref(); //点击员工的id
let loadingTable = ref(true); //等待表格请求的动画
let loadingTree = ref(true); //等待哦树型控件请求的动画
let visbleExcel = ref(false); //导入的弹框的开关
let file = ref("");
let xiaoxiRef = ref(); //消息弹框的节点
let staffs = ref([]); //要发消息的员工列表
let msgGrade = ref([
  //消息等级
  {
    label: "通知消息",
    value: 1,
  },
  {
    label: "提示消息",
    value: 2,
  },
  {
    label: "重要消息",
    value: 3,
  },
  {
    label: "紧急消息",
    value: 4,
  },
]);
let msgType = ref(); //消息类型
let userIds = ref([]); //发给消息的员工id
let msgContent = ref(""); //消息内容

// ##群送消息
function cancel() {
  //取消发送
  xiaoxiRef.value.close();
}
function sureSendMsg() {
  //确认发送
  if (!msgType) {
    ElMessage.warning("请选择消息类型");
    return;
  }

  if (!userIds.value.length) {
    ElMessage.warning("请选择要发送消息的员工");
    return;
  }
  if (msgContent.value < 5 || msgContent.value > 100) {
    ElMessage.warning("消息内容在5-100字之间");
    return;
  }
  let params = {
    userIds: userIds.value,
    type: msgType.value,
    content: msgContent.value,
  };
  axios.post("/sys/messageMuch", params).then((res) => {
    if (res.success) {
      ElMessage.success(res.message);
      xiaoxiRef.value.close();
    } else {
      ElMessage.error(res.message);
    }
  });
}
function closeStaff(id) {
  //取消给谁发送
  staffs.value = staffs.value.filter((k) => k.id != id);
  userIds.value = staffs.value.map((k) => k.id);
}
function sendMessage() {
  //  console.log(multipleSelection.value);

  if (multipleSelection.value.length == 0) {
    ElMessage.warning("请选择要发送消息的员工");
    return;
  }

  staffs.value = multipleSelection.value;
  userIds.value = staffs.value.map((k) => k.id);
  xiaoxiRef.value.open();
}

// ##下载模板
async function xiazai() {
  //  向后端请求Excel文件数据
  const res = await axios.get("/sys/user/import/template", 
  {
    responseType: "blob", // 设置响应类型为blob
  });
  console.log(res);
  // 设置响应类型为blob，可以将后端相应的文件转换成自己可以使用的格式，之前是乱码，现在是一个对象，对象中sizes属性是文件的大小，type是文件的格式
  const blob = new Blob([res], {
    type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  });
  console.log(blob);
  const reader = new FileReader();
  reader.onload = () => {
    const data = new Uint8Array(reader.result);
    const workbook = XLSX.read(data, { type: "array" });
    // 处理Excel文件，例如获取数据、修改数据等
    const sheetName = workbook.SheetNames[0];
    const worksheet = workbook.Sheets[sheetName];  
    const excelData = XLSX.utils.sheet_to_json(worksheet, { header: 1 }); 
    // 在这里可以对excelData进行处理，比如展示在页面上或者进行其他操作
    // 最后可以选择是否下载处理后的Excel文件
    const newWorkbook = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(newWorkbook, worksheet, sheetName);
    XLSX.writeFile(newWorkbook, "员工导入模板（XLSX版本）.xlsx");
  };
  reader.readAsArrayBuffer(blob);  //将文件转换成二进制工作流
}

// ##导入excel
function fileChange(val) {
  // console.log(file);
  file.value = val.raw;
  console.log(file.value, 111);
}
// 确认上传
function importExcel() {
  let reader = new FileReader();
  reader.readAsArrayBuffer(file.value);
  reader.onload = function () {
    axios
      .post(
        "/sys/user/import",
        { file: file.value },
        {
          headers: {
            "Content-Type": "multipart/form-data",
          },
        }
      )
      .then((res) => {
        // console.log(res);
        if (res.success) {
          ElMessage.success("导入成功");
          visbleExcel.value = false;
          getList();
        } else {
          ElMessage.error(res.message);
        }
      });
  };
}

// ##导出excel
function excelExport() {
  // 拿到要导出的对象
  // 创建工作簿
  const workbook = new ExcelJS.Workbook();
  // 添加工作表，名为sheet1
  const sheet1 = workbook.addWorksheet("sheet1");
  // 添加表格头的标题和样式
  sheet1.addRow();
  // 导出数据列表
  let arr = multipleSelection.value.map((k) => { //制作成自己可以使用的格式
    return {
      姓名: k.username,
      手机号: k.mobile,
      入职时间: k.timeOfEntry,
      聘用形式: (k.formOfEmployment = 1 ? "正式" : "非正式"),
      工号: k.workNumber,
      部门: k.departmentName,
    };
  });
  let data = arr ? arr : [];
  console.log(data);
  if (data.length == 0) {
    ElMessage.error("请选择要导出的内容");
    return;
  }
  // 获取表头所有键
  const headers = Object.keys(data[0]);
  // 将标题写入第一行
  sheet1.addRow(headers);
  // 将数据写入工作表
  data.forEach((row, index) => {
    const values = Object.values(row);
    const content = sheet1.getColumn(index + 1); // 获取第index+1列
    content.font = { bold: true }; // 设置字体加粗
    content.alignment = { horizontal: "center" }; // 设置水平居中
    content.fill = { type: "pattern", pattern: "solid", fgColor: { argb: "FFFF00" } }; // 设置背景颜色
    // 设置每一列的宽
    content.width = 30;
    sheet1.addRow(values); // 添加一行
  });
  // 导出表格文件
  workbook.xlsx
    .writeBuffer() //将工作簿（workbook）的内容写入到文件缓冲区（buffer）。
    .then((buffer) => {
      //写入文件成功的时候
      let file = new Blob([buffer], { type: "application/octet-stream" }); //创建一个Blob对象，用于存储文件内容。[buffer]表示将文件缓冲区中的内容作为参数传递，{ type: "application/octet-stream" }表示设置文件的MIME类型为application/octet-stream，即二进制流。
      FileSaver.saveAs(file, "员工信息表.xlsx"); //要保存的文件，要保存的文件名
    })
    .catch((error) => console.log("Error writing excel export", error));
}

// ##点击部门的时候
function nodeClick(obj) {
  console.log(obj, "obj");
  departmentId.value = obj.id;
  getList();
}
// ##搜索姓名
watch(keyword, () => {
  getList();
});

// ##部门选中事件
// function handleCheckChange(checkedNodes,checkedKey,halfCheckedNodes,halfCheckedKeys) {
//   console.log(checkedNodes,checkedKey,halfCheckedNodes,halfCheckedKeys, "当部门选中的时候");
// }
//##表格中选中事件
const handleSelectionChange = (val) => {
  multipleSelection.value = val;
  console.log(multipleSelection.value);
};
//## 分页
function changePage(pageNum, sizeNum) {
  page.value = pageNum;
  pagesize.value = sizeNum;
  getList();
}
//## 查看
function look(id) {
  // console.log(id);
  router.push({ path: "/editStaff", query: { id: id } });
}
//## 删除
function del(id) {
  console.log(id);
  axios.delete(`/sys/user/${id}`).then((res) => {
    // console.log(res);
    if (res.success) {
      getList();
      ElMessage.success(res.message);
    }
  });
}
//## 角色
function role(id) {
  roleId.value = id;
  axios.get("/sys/role/list/enabled").then((res) => {
    if (res.success) {
      console.log(res, "角色");
      dialogVisible.value = true;
      roleList.value = res.data;
      // 请求个人信息
      axios.get(`/sys/user/${id}`).then((re) => {
        console.log(re, "个人信息、、、、、、、、、");
        roleIds.value = re.data.roleIds;
      });
    }
  });
}
// 修改
function confirm() {
  axios
    .put(`/sys/user/assignRoles`, {
      id: roleId.value,
      roleIds: roleIds.value,
    })
    .then((res) => {
      console.log(res, "修改角色");
      if (res.success) {
        ElMessage.success(res.message);
        dialogVisible.value = false;
      }
    });
}
// ##监听路由的变化
watch(route, () => {
  // console.log(route,'路由发生了变化');
  panduan();
  //   getlist()
});
onMounted(() => {
  getList();
  getDepartment();
  //   页面初始化的时候判断路由是否是添加或者编辑
  panduan();
});
// 判断路由位置
function panduan() {
  if (
    route.matched[route.matched.length - 1].path == "/addStaff" ||
    route.matched[route.matched.length - 1].path == "/editStaff"
  ) {
    isadd.value = true;
  } else {
    isadd.value = false;
  }
}
// 获取数据
function getList() {
  loadingTable.value = true;

  axios
    .get("/sys/user", {
      params: {
        page: page.value,
        pagesize: pagesize.value,
        departmentId: departmentId.value,
        keyword: keyword.value,
      },
    })
    .then((res) => {
      loadingTable.value = false;
      console.log(res);
      if (res.message == "获取员工列表成功") {
        list.value = res.data.rows;
        total.value = res.data.total * 1;
      }
    });
}
function getDepartment() {
  loadingTree.value = true;
  //获取部门
  axios.get("/company/department").then((res) => {
    console.log(res, "部门信息");
    loadingTree.value = false;
    if (res.success) {
      // 使用无限级分类
      let arr = createCategoryTree(res.data);
      //   console.log(arr);
      treeArr.value = arr;
    }
    //
  });
}

// 定义一个函数 createCategoryTree，用于将平面的分类数据转换为树形结构
const createCategoryTree = (categories) => {
  // 创建一个对象 categoryMap 用于存储每个分类的节点信息，以分类的 id 作为键
  let categoryMap = {};
  // 创建一个对象 root 用于存储根节点信息，根节点即父节点 pid 为 0 的节点
  let root = {};
  // 遍历分类数据，为每个分类创建一个节点对象，并存储到 categoryMap 中
  categories.forEach((item) => {
    // 创建节点对象，包含分类本身的所有信息和一个空的 children 数组用于存储子节点
    const node = { ...item, children: [] };
    // 将节点对象存储到 categoryMap 中，键为分类的 id
    categoryMap[item.id] = { ...node };
    // 如果当前节点的父节点 id（pid）为 0，说明它是一个根节点，将其存储到 root 对象中
    if (item.pid === 0) {
      root[item.id] = { ...node };
    }
  });
  // console.log(categoryMap);
  // console.log(root);
  // 再次遍历分类数据，将每个节点添加到其父节点的 children 数组中
  categories.forEach((item) => {
    // 如果节点的父节点 id（pid）不为 0，说明它不是根节点
    if (item.pid !== 0) {
      // console.log(item);
      // 通过 pid 从 categoryMap 中找到父节点对象
      const parent = categoryMap[item.pid];
      // console.log(parent);
      // 从 categoryMap 中找到当前节点对象
      const child = { ...categoryMap[item.id] };
      // 将当前节点对象添加到父节点的 children 数组中
      parent?.children.push({ ...child });
    }
  });
  console.log(root);
  // 从 root 对象中提取所有根节点的数组
  let arr = Object.values(root);
  // 返回根节点数组，这个数组构成了分类的树形结构
  return arr;
};
</script>

<style scoped lang="less">
.pagination {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 30px 0;
}

.el-table {
  img {
    height: 40px;
    border-radius: 50%;
  }

  .tou {
    height: 40px;
    width: 40px;
    background-color: rgb(84, 170, 220);
    color: aliceblue;
    text-align: center;
    line-height: 35px;
    border-radius: 50%;
  }
}

.wapper {
  font-size: 20px;
  display: flex;
  justify-content: space-between;
  height: 100%;
  overflow: auto;
  background-color: #fff;

  .left {
    width: 20%;
    height: 100%;
    border-right: 1px solid #ccc;
    padding: 10px;
    font-size: 20px;

    .el-input {
      height: 35px;
      margin-bottom: 30px;
    }
  }

  .right {
    width: 80%;

    .title {
      display: flex;
      justify-content: space-between;
      height: 40px;
      align-items: center;
      margin-top: 30px;
    }
  }
}

.staffs {
  min-height: 100px;
  border: 1px solid #e0e0e0;
  border-radius: 20px;
}

.el-tag {
  height: 35px;
  padding: 10px;
  margin: 10px 20px;
}

.tem {
  margin-bottom: 30px;
  margin-left: 30px;

  .title {
    font-weight: 700;
    font-size: 18px;
  }
}
</style>
